home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
pctjoc85.arc
/
WHERE.C
< prev
next >
Wrap
Text File
|
1985-07-25
|
16KB
|
409 lines
/***************************************************************
* *
* WHERE *
* *
* Where is a program to locate files on the PC hard disk. *
* It requires DOS 2.x or 3.x. *
* *
* The command line syntax is: *
* where [starting directory]filename.ext *
* *
* Written by Mark S. Ackerman *
* *
* Copyright 1984, 1985 by Mark S. Ackerman. Permission is *
* granted for unlimited copies if not sold or otherwise *
* exchanged for gain. *
* *
***************************************************************/
/***************************************************************
* The C header files *
* These identify library routines like printf() and intcall() *
***************************************************************/
#include <stdio.h> /* standard i/o */
#include <dos.h> /* functions for DOS interrupt calls */
/***************************************************************
* Definition of DOS Disk Transfer Area (DTA) *
***************************************************************/
/***************************************************************
* Structure for MS-DOS date and time fields *
* See pages 4-6 and 4-7 of the DOS 2.1 technical *
* reference manual for more information *
* This structure is used in the next structure definition *
***************************************************************/
struct msdos_date
{
unsigned ms_sec : 5; /* time in 2 sec. int (5 bits)*/
unsigned ms_min : 6; /* minutes (6 bits) */
unsigned ms_hour : 5; /* hours (5 bits) */
unsigned ms_day : 5; /* day of month (5 bits) */
unsigned ms_month : 4; /* month (4 bits) */
unsigned ms_year : 7; /* year since 1980 (7 bits) */
};
/***************************************************************
* Structure filled in by MS-DOS for interrupt 21 calls *
* See page 5-46 of the DOS 2.1 technical reference *
* manual for more information *
***************************************************************/
struct DTA
{
char DTA_dosinfo[21]; /* used by DOS */
char DTA_attr; /* file attribute byte */
struct msdos_date DTA_date; /* date struct. as above */
long DTA_size; /* file size */
char DTA_filename[13]; /* file name (w/o path) */
};
/***************************************************************
* Definitions of constants *
***************************************************************/
#define not ! /* for ease of reading (C uses a !
character for logical not's) */
#define and & /* for ease of reading (C uses a &
character for bit-wise logical and's) */
#define carry_set 0x0001 /* mask for flag register
for carry bit */
#define no_type 0x00 /* no bits set on file attribute byte*/
#define directory_type 0x10 /* directory file bit on file
info word */
#define no_more_files 18 /* DOS return code for
no more files */
#define end_of_string '\0' /* C uses a binary zero to
signal end of string */
#define backslash '\\' /* the backslash character */
char *month[] = {
"Jan","Feb","Mar","Apr","May","Jun",
"Jul","Aug","Sep","Oct","Nov","Dec"
};
char *time_of_day[2] = {"AM","PM"};
/***************************************************************
* Define the type "filename" *
* to be a string of 51 characters *
***************************************************************/
typedef char filename[51];
/***************************************************************
* *
* The following filename strings are used in the program: *
* *
* check_string filename to be searched for *
* filename in the command line) *
* directory_string directory name to be searched *
* newdirectory_string directory name to be searched *
* on next recursive call *
* current_string temporary string for searching *
* in a specific directory *
***************************************************************/
/***************************************************************
* Definition of any forward-referenced functions *
***************************************************************/
char *DATE();
/***************************************************************
* Global variables *
***************************************************************/
filename check_string; /* this string "remembers" user input */
struct reg registers; /* structure to allow access to indiv.*/
/* registers for interrupts */
char datestring[40]; /* print output string for dates */
/***************************************************************
* MAIN() -- the beginning of the code *
***************************************************************/
main(argc,argv)
int argc;
char *argv[];
{
filename directory_string; /* directory to be searched */
char *incoming_filename; /* address of filename in
command line argument
(ie, the filename) */
char *last_location; /* address of last backslash in
command line argument */
char *incoming_string; /* address of
command line argument */
int last_directory_char; /* last character
in directory string */
/********************************************************
* check number of incoming arguments *
* if incorrect, write an error message *
********************************************************/
if (argc not= 2)
printf
("usage is: WHERE [starting directory]filename.ext\n\n");
else
{
/********************************************************
* incoming_string is set to the first argument in the *
* command line *
* The incoming_string is then searched for the last *
* occurrence of a backslash to find the end of *
* the directory name. *
********************************************************/
incoming_string = *(++argv);
last_location = rindex(incoming_string,backslash);
/********************************************************
* If there was not a backslash (and therefore the *
* beginning directory is the root directory) *
* begin *
* copy command line argument into check_string *
* copy root directory into directory_string *
* end *
* else *
* (if there was a backslash and therefore a beginning *
* directory specified in the command line) *
* begin *
* set the incoming_filename to the next character *
* past the backslash *
* copy the incoming_filename into check_string *
* copy the command line argument into *
* directory_string *
* terminate directory_string just after the *
* last backslash (therefore leaving only the *
* the directory name in the string) *
* end *
********************************************************/
if (last_location == NULL)
{
strcpy(check_string,incoming_string);
strcpy(directory_string,"\\");
}
else
{
incoming_filename = last_location + 1;
strcpy(check_string,incoming_filename);
strcpy(directory_string,incoming_string);
last_directory_char = incoming_filename - incoming_string;
directory_string[last_directory_char] = end_of_string;
}
/********************************************************
* start 'er up *
********************************************************/
LOOK(directory_string);
}
return;
}
LOOK(directory_string)
/********************************************************
* LOOK is the recursive procedure in WHERE *
* It is called once for each subdirectory *
********************************************************/
char *directory_string;
{
struct DTA current_DTA; /* used to return data from DOS */
filename newdirectory_string; /* the directory to be
searched on the next
call to LOOK() */
filename current_string; /* temporary filename
string for searching for
directories */
/********************************************************
* Form current_string by copying directory_string and *
* and then concatenating "*.*" to look through all *
* files *
********************************************************/
strcpy(current_string,directory_string);
strcat(current_string,"*.*");
/********************************************************
* Set the Disk Transfer Area in DOS to the current_DTA *
* structure *
* Get the first subdirectory in this directory *
********************************************************/
SET_DTA(¤t_DTA);
GET_FIRST(current_string,directory_type);
/********************************************************
* while there are more subdirectories in this directory *
* begin *
* double check for proper directories (see text) *
* if a directory *
* begin *
* set up the newdirectory_string for the *
* next call to LOOK (see text) *
* call LOOK *
* reset Disk Transfer Address (see text) *
* end *
* look for next directory *
* end *
********************************************************/
while (not(registers.r_flags and carry_set))
{
if (current_DTA.DTA_attr == directory_type &&
current_DTA.DTA_filename[0] not= '.')
{
strcpy(newdirectory_string,directory_string);
strcat(newdirectory_string,current_DTA.DTA_filename);
strcat(newdirectory_string,"\\");
LOOK(newdirectory_string);
SET_DTA(¤t_DTA);
}
GET_NEXT();
}
/********************************************************
* if there are no more subdirectories in this directory *
* look for files *
* else *
* print an error message *
********************************************************/
if (registers.r_ax == no_more_files)
GET_FILES(directory_string,¤t_DTA);
else
printf("problem with looking thru %s\n",directory_string);
return;
}
GET_FILES(directory_string,current_DTA)
/********************************************************
* GET_FILES *
* is called once per directory to look for the *
* actual files matching the search string *
********************************************************/
char *directory_string;
struct DTA *current_DTA;
{
filename current_string;
/********************************************************
* Form current_string by copying directory_string into *
* it and then concatenating the check_string onto *
* the end *
********************************************************/
strcpy(current_string,directory_string);
strcat(current_string,check_string);
/********************************************************
* Get the first file that matches current_string *
********************************************************/
GET_FIRST(current_string,no_type);
/********************************************************
* while there are more files that match the search *
* string: *
* begin *
* print the file information *
* get the next file *
* end *
********************************************************/
while (not(registers.r_flags and carry_set))
{
printf(" %10D %s %s%s\n", (*current_DTA).DTA_size,
DATE(&((*current_DTA).DTA_date)), directory_string,
(*current_DTA).DTA_filename);
GET_NEXT();
}
/********************************************************
* if error in looking for a file *
* print error message and return *
********************************************************/
if (registers.r_ax not= no_more_files)
printf("problem with looking for %s\n",current_string);
return;
}
GET_NEXT()
{
/********************************************************
* GET_NEXT does an interrupt 21h, function 4Fh *
********************************************************/
registers.r_ax = 0x4f00;
intcall(®isters,®isters,0x21);
return;
}
SET_DTA(current_DTA)
struct DTA *current_DTA;
{
/********************************************************
* SET_DTA does an interrupt 21h, function 1Ah *
* The DS:DX pair is set to the address of the *
* current_DTA data structure *
********************************************************/
registers.r_ax = 0x1a00;
ptoreg(dsreg,registers.r_dx,registers.r_ds,current_DTA);
intcall(®isters,®isters,0x21);
return;
}
GET_FIRST(search_string,filetype)
char *search_string;
int filetype;
{
/********************************************************
* GET_FIRST does an interrupt 21h, function 4Eh *
* The CX register is set to either normal or *
* directory type (see text) *
* The DS:DX pair is set to the address of the *
* search string *
********************************************************/
registers.r_ax = 0x4e00;
registers.r_cx = filetype;
ptoreg(dsreg,registers.r_dx,registers.r_ds,search_string);
intcall(®isters,®isters,0x21);
return;
}
char *DATE(dateptr)
struct msdos_date *dateptr;
{
/********************************************************
* DATE takes the date field from the current DTA *
* structure and returns a string containing the *
* information in formatted ASCII *
********************************************************/
sprintf(datestring, "%02d-%02d-%2d %02d:%02d %s",
dateptr->ms_month, dateptr->ms_day,
dateptr->ms_year+80, (dateptr->ms_hour)%12,
dateptr->ms_min, time_of_day[((dateptr->ms_hour)/12)]);
return(datestring);
}